home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1992 by Panagiotis Tsirigotis
- * All rights reserved. The file named COPYRIGHT specifies the terms
- * and conditions for redistribution.
- */
-
- static char RCSid[] = "$Id: intcommon.c,v 5.1 1992/11/01 00:01:21 panos Exp $" ;
-
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <signal.h>
- #include <syslog.h>
- #include <errno.h>
-
- #include "int.h"
- #include "defs.h"
- #include "server.h"
- #include "config.h"
- #include "state.h"
-
- void msg() ;
-
-
- void int_fail( ip, syscall )
- struct intercept *ip ;
- char *syscall ;
- {
- msg( LOG_ERR, "fail", "%s failed: %m", syscall ) ;
- (*ip->ops->exit)() ;
- /* NOTREACHED */
- }
-
-
- /*
- * Returns either a positive number or -1
- */
- int int_select( max, read_mask )
- int max ;
- fd_set *read_mask ;
- {
- char *func = "int_select" ;
-
- for ( ;; )
- {
- int n_ready ;
-
- n_ready = select( max+1, read_mask,
- FD_SET_NULL, FD_SET_NULL, TIMEVAL_NULL ) ;
- if ( n_ready > 0 )
- return( n_ready ) ;
- else if ( n_ready == -1 )
- if ( errno == EINTR )
- continue ;
- else
- {
- msg( LOG_ERR, func, "select: %m" ) ;
- return( -1 ) ;
- }
- }
- }
-
-
- void int_exit( ip )
- struct intercept *ip ;
- {
- int status = INT_SERVER( ip )->exit_status ;
- char *func = "int_exit" ;
-
- if ( debug.on )
- {
- if ( PROC_EXITED( status ) )
- msg( LOG_DEBUG, func, "intercepted server died" ) ;
- else if ( PROC_SIGNALED( status ) )
- msg( LOG_DEBUG, func, "intercepted server received signal %d",
- PROC_TERMSIG( status ) ) ;
- }
- _exit( (int) PROC_EXITSTATUS( status ) ) ;
- }
-
-
- /*
- * The ops vector must be installed before invoking this function
- */
- void int_init( ip, serp )
- struct intercept *ip ;
- struct server *serp ;
- {
- int flags ;
- register unsigned u ;
- char *func = "int_init" ;
- void int_sighandler() ;
-
- /*
- * Close all unneeded descriptors
- */
- for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
- {
- struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
-
- if ( sp == SERVER_SERVICE( serp ) )
- continue ;
- if ( LOG( CONF( sp ) )->log_type == L_FILE )
- xlog_destroy( SDATA( sp )->log_handle ) ;
- (void) close( SVC_FD( sp ) ) ;
- }
-
- /*
- * Setup signal handling
- */
- if ( (int) signal( SERVER_EXIT_SIG, int_sighandler ) == -1 )
- int_fail( ip, "signal" ) ;
- if ( (int) signal( INTERCEPT_SIG, int_sighandler ) == -1 )
- int_fail( ip, "signal" ) ;
- if ( (int) signal( SIGTERM, int_sighandler ) == -1 )
- int_fail( ip, "signal" ) ;
-
- /*
- * Initialize state
- */
- INTERCEPT( ip ) = TRUE ;
- *INT_SERVER( ip ) = *serp ;
- INT_REMOTE( ip ) = SERVER_FD( serp ) ;
-
- flags = FSM_RETURN_ERROR ;
- #ifdef DEBUG
- flags |= FSM_ZERO_FREE ;
- #endif
- INT_ALLOCATOR( ip ) = fsm_create( sizeof( channel_s ), 0, flags ) ;
- if ( INT_ALLOCATOR( ip ) == NULL )
- {
- msg( LOG_ERR, func, ES_NOMEM ) ;
- (*ip->ops->exit)() ;
- }
-
- INT_CONNECTIONS( ip ) = pset_create( 0, 0 ) ;
- if ( INT_CONNECTIONS( ip ) == NULL )
- {
- msg( LOG_ERR, func, ES_NOMEM ) ;
- (*ip->ops->exit)() ;
- }
- }
-
-
-
- /*
- * Make a new connection to the local server
- */
- channel_s *int_newconn( ip, sinp, remote_socket )
- struct intercept *ip ;
- struct sockaddr_in *sinp ;
- int remote_socket ;
- {
- int socket_type = CONF( INT_SERVER( ip )->sp )->socket_type ;
- struct sockaddr_in *local = INT_LOCALADDR( ip ) ;
- channel_s *chp ;
- int sd ;
- char *func = "int_newconn" ;
-
- /*
- * Get a socket and connect it to the local address
- */
- if ( ( sd = socket( AF_INET, socket_type, 0 ) ) == -1 )
- {
- msg( LOG_ERR, func, "socket creation: %m" ) ;
- return( NULL ) ;
- }
-
- if ( connect( sd, SA( local ), sizeof( *local ) ) == -1 )
- {
- msg( LOG_ERR, func, "connect: %m" ) ;
- (void) close( sd ) ;
- return( NULL ) ;
- }
-
- chp = CHP( fsm_alloc( INT_ALLOCATOR( ip ) ) ) ;
- if ( chp == NULL )
- {
- msg( LOG_ERR, func, ES_NOMEM ) ;
- (void) close( sd ) ;
- return( NULL ) ;
- }
-
- if ( pset_add( INT_CONNECTIONS( ip ), chp ) == NULL )
- {
- msg( LOG_ERR, func, ES_NOMEM ) ;
- fsm_free( INT_ALLOCATOR( ip ), (char *) chp ) ;
- (void) close( sd ) ;
- return( NULL ) ;
- }
-
- chp->state = GOOD_CHANNEL ;
- chp->from = *sinp ;
- chp->local_socket = sd ;
- chp->remote_socket = remote_socket ;
- return( chp ) ;
- }
-
-
-
- /*
- * Check if the (address,port) in sinp is already in the connection table.
- * Return value:
- * a connection pointer if the address is found
- * NULL if the address if not found
- *
- * *addr_checked is set to TRUE of FALSE depending on whether there
- * is already a connection from the same IP address in the table.
- */
- channel_s *int_lookupconn( ip, sinp, addr_checked )
- struct intercept *ip ;
- struct sockaddr_in *sinp ;
- bool_int *addr_checked ;
- {
- register unsigned u ;
- register pset_h conntab = INT_CONNECTIONS( ip ) ;
-
- *addr_checked = FALSE ;
-
- for ( u = 0 ; u < pset_count( conntab ) ; u++ )
- {
- register channel_s *chp = CHP( pset_pointer( conntab, u ) ) ;
-
- if ( chp->from.sin_addr.s_addr == sinp->sin_addr.s_addr )
- {
- *addr_checked |= TRUE ;
- if ( chp->from.sin_port == sinp->sin_port )
- return( chp ) ;
- }
- }
- return( NULL ) ;
- }
-
-
-